/*
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/
#include "Abstract.h"

using namespace std;

string AbstractOption::allKeys; 
string AbstractOption::allOptions; 

size_t AbstractArg::requiredCount = 0;

void trim(string& str);

/**
 *  @brief remove all unused spaces placed before and after the characters into a string
 *  @see http://www.codeproject.com/KB/stl/stdstringtrim.aspx
 * 
 */

void trim(string& str)
{
  string::size_type pos = str.find_last_not_of(' ');
  if(pos != string::npos) {
    str.erase(pos + 1);
    pos = str.find_first_not_of(' ');
    if(pos != string::npos) str.erase(0, pos);
  }
  else str.erase(str.begin(), str.end());
}


AbstractArg::AbstractArg(const char* parceStr, const char* desc, bool m) 
{
	parser = parceStr; 
	description = desc;
	optional = m;
	initialized = false;
	if (!optional)
		++requiredCount;
}

AbstractArg::AbstractArg(const char* desc, bool m) 
{
	parser = NULL; 
	description = desc;
	optional = m;
	initialized = false;
	if (!optional)
		++requiredCount;
}

AbstractArg::~AbstractArg() 
{
	requiredCount = 0;
}


int AbstractArg::PrintDecs(std::ostream& out/* = std::cout*/)
{
	if (description != NULL) {
		
		if (optional) 
			out << "[";
		
		out << description;
			
		if (optional) 
			out << "]";
	}
	return (0);
}



AbstractOption::AbstractOption(char k, const char* desc, AbstractArg* pArg) : 
					description(desc),
					verboseKey(NULL),
					pArg(pArg)
{
	if (allKeys.find(k) == string::npos) {
		allKeys += k;
		key = k;
	}
	else
		throw ERR_UNIQUE;		
}

AbstractOption::AbstractOption(char k, const char* verbKey, const char* desc, AbstractArg* pArg): 
					description(desc),
					verboseKey(verbKey),
					pArg(pArg)
{
	if (allKeys.find(k) == string::npos) {
		allKeys += k;
		key = k;
	}
	else
		throw ERR_UNIQUE;			
}

AbstractOption::~AbstractOption()
{
	size_t n = allKeys.find(key);
	if (n == string::npos) 
		throw ERR_SW;		
	else {
		
		allKeys.erase(n);
	}
	n = allOptions.find(key);
	if (n != string::npos) 
		allOptions.erase(n);
}


int AbstractOption::VerboseKeyLen()
{
	if (verboseKey != NULL) {
		
		return strlen(verboseKey);
	}
	return 0;
}

int AbstractOption::PrintDecs(int& offset, std::ostream& out/* = std::cout*/)
{
	string s;

	out << "-" << key << "\t";
	
	if (verboseKey != NULL) {
		
		int len = strlen(verboseKey);
		out << "--" <<  verboseKey;
		s.append(offset + 5 - len, ' ');
	}
	else {
	
		s.append(offset + 7 /* 5 + '--'*/, ' ');
	}

	out << s << description;
/*	if (pArg != NULL) {

		out << "; expected value: ";
		pArg->PrintDecs(out);
	}*/
	return (0);
}


